

/*
// 获取当前时间对象
DateTime now = DateTime.now();

// 创建的时间对象为 2021年1月1日
DateTime y2k = DateTime(2021);

// 创建的时间对象为 2021年1月2日
y2k = DateTime(2021, 1, 2);

// 创建的时间对象为 2021年1月1日  UTC
y2k = DateTime.utc(2021);

// 根据毫秒来创建时间对象
y2k = DateTime.fromMillisecondsSinceEpoch(946684800000,
    isUtc: true);

// 将 ISO 8601 类型的字符串时间解析为时间对象.
y2k = DateTime.parse('2000-01-01T00:00:00Z');


DateTime 对象可以做直接比较，有isBefore、isAfter、isAtSameMomentAs、compareTo 等方法

  //创建时间对象  2021-1-2
  DateTime date1 = DateTime(2021, 1, 2);
  //创建时间对象 2021-1-3
  DateTime date2 = DateTime(2021, 1, 3);
  // 时间比较  date1 是否在 date2之前  true
  bool isBefore = date1.isBefore(date2);
  print('isBefore $isBefore'); // 在之前

  // 时间比较  date1 是否在 date2之后  false
  bool isAfter = date1.isAfter(date2);
  print('isAfter $isAfter');

  // 时间比较  date1 与 date2是否相等 false
  bool isAtSameMomentAs = date1.isAtSameMomentAs(date2);
  print('isAtSameMomentAs  $isAtSameMomentAs');


  //两个时间相比较 大于返回1；等于返回0；小于返回-1。
  int compareTo = date1.compareTo(date2);
  print('compareTo $compareTo'); // -1


DateTime 时间差计算
计算时间差的方式还是比较多的，在这里我们直接使用 DateTime 的difference 方法来对时间DateTime进行相减操作

    //创建时间对象  2021-1-2
  DateTime date1 = DateTime(2021, 1, 2);
  //创建时间对象 2021-1-3
  DateTime date2 = DateTime(2021, 1, 3);

  //计算两个时间差 date1 - date2
  Duration difference = date1.difference(date2);
  print('时间差 difference $difference'); //  -24:00:00.000000

  int inMilliseconds  = difference.inMilliseconds ;
  int intHours = difference.inHours;
  int inDays = difference.inDays;

  print('时间差 毫秒 $inMilliseconds');
  print('时间差 小时 $intHours');
  print('时间差 天 $inDays');

我这里是 2021-2-1 减去 2021-2-2 ，所以相减出来是负数，我们可以使用 Duration 对象的 abs() 求绝对值的方法来获取正数

  //计算两个时间差 date1 - date2
  Duration difference = date1.difference(date2).abs();


字符串转日期

 DateTime date1 = DateTime.parse("2021-01-01");
 print(date1);//2021-01-01 00:00:00.000
日期转指定格式的字符串时间

TimeOfDay.now()


初始化时间:
  需要注意的是，在 Dart 中，日期和时间都是不可变对象，一旦创建就无法修改。如果需要对日期和时间进行操作，必须创建一个新的对象。
  DateTime now = DateTime.now(); // 获取当前时间
DateTime dt1 = DateTime(2022); // 指定年份
DateTime dt2 = DateTime(2022, 8); // 指定年份和月份
DateTime dt3 = DateTime(2022, 8, 5); // 指定年份、月份和日期
DateTime dt4 = DateTime.utc(2022, 8, 5, 14, 30); // 指定 UTC 时间

 */

import 'package:intl/intl.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_log.dart';

abstract class XDateUtils{

  static const String formatTimeDefault1='yyyy-MM-dd HH:mm:ss';
  static const String formatTimeDefault2='yyyy-MM-dd HH:mm:ss.SSS';
  static const String formatTimeDefault3='yyyy-MM-dd';
  static const String formatTimeDefault4='yyyy/MM/dd';
  static const String formatTimeDefault5='yyyy/MM/dd HH:mm:ss';
  static const String formatTimeDefault6='HH:mm:ss';
  static const String formatTimeDefault7='yyyy-MM';
  static const String formatTimeDefault8='yyyy';

  /*
  //获取对应的毫秒
    // int time = dateTime.microsecondsSinceEpoch;
    // print("毫秒 $time");

    //获取当前时间的年
    int year = dateTime.year;
    //获取当前时间的月(下标从1开始, 1~12)
    int month = dateTime.month;
    //获取当前时间的日
    int day = dateTime.day;
    //获取当前时间的时
    int hour = dateTime.hour;
    //获取当前时间的分
    int minute = dateTime.minute;
    //获取当前时间的秒
    int second = dateTime.second;
    //获取当前时间的毫秒
    int millisecond = dateTime.millisecond;

    String timestamp='';
    if('年-月-日 时:分:秒.毫秒'==format){
      //2023-02-16 17:08:19.295
      timestamp = "${year.toString()}-${month.toString().padLeft(2,'0')}-${day.toString().padLeft(2,'0')} ${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}:${second.toString().padLeft(2, '0')}.${millisecond.toString()}";
    }else if('年-月-日'==format){
      //2023-02-16
      timestamp = "${year.toString()}-${month.toString().padLeft(2,'0')}-${day.toString().padLeft(2,'0')}";
    }else{
      //2023-02-16 17:08:19.295
      timestamp = "${year.toString()}-${month.toString().padLeft(2,'0')}-${day.toString().padLeft(2,'0')} ${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}:${second.toString().padLeft(2, '0')}.${millisecond.toString()}";
    }

    获得星期几:
    var weekday = [" ", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"];`
    //变量直接调用日期函数weekday
    weekday[dateTime.weekday];
   */

  static final List<String> _weekdayList0=[" ", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"];
  static final List<String> _weekdayList1=[" ", "周一", "周二", "周三", "周四", "周五", "周六", "周日"];

  //获得星期几:
  static String getStringWeekday(
      DateTime dateTime,
      {
        int type=0,
      }
      ){
    int weekday=dateTime.weekday;// 周几：1~7
    if(type==1){
      return _weekdayList1[weekday];
    }
    //默认
    return _weekdayList0[weekday];
  }

  //当前时间(毫秒)
  static int getCurrentTime_ms(){
    return getTime_ms();
  }
  //
  static int getTime_ms({DateTime? dateTime}){
    dateTime??=DateTime.now();
    return dateTime.millisecondsSinceEpoch;
  }


  //截取,年月日,去除时分秒 2024-03-03
  static String getSubStringDate(String time){
    return time.length>10?time.substring(0,10):time;
  }

  //获得当前时间字符串
  static String getCurrentTime_String({String? format}){
    return getStringTimeFormat(format:format);
  }

  //获取字符串格式时间
  static String getStringTimeFormat(
      {
        DateTime? dateTime, //默认当前时间
        String? format,
      }
      ){
    //当前
    dateTime ??= DateTime.now();
    format??= formatTimeDefault1;

    /*
  print(DateFormat('EEE',"zh_CN").format(DateTime.now())); //周五
  print(DateFormat('EEEE',"zh_CN").format(DateTime.now())); //星期五
  print(DateFormat('MM',"zh_CN").format(DateTime.now())); //11
  print(DateFormat('MMM',"zh_CN").format(DateTime.now())); //11月
  print(DateFormat('MMMM',"zh_CN").format(DateTime.now()));//十一月
     */

    return DateFormat(format).format(dateTime);

  }

  /*
  "2012-02-27"
  "2012-02-27 13:27:00"
  "2012-02-27 13:27:00.123"
  "20120227 13:27:00"
   */
  static DateTime? getDateTimeWithString(String timeStr){
    try{
      return DateTime.parse(timeStr);
    }catch(e){
      XLogUtils.printLog('$e');
    }
    return null;
  }

  //通过毫秒获得对应的DateTime
  static DateTime? getDateTimeWithMilliseconds(int ms){
    try{
      return DateTime.fromMillisecondsSinceEpoch(ms);
    }catch(e){
      XLogUtils.printLog('$e');
    }
    return null;
  }

  //是否当天
  static bool isToday(DateTime date) {
    final now = DateTime.now();
    return date.year == now.year && date.month == now.month && date.day == now.day;
  }

  //是否当月
  static bool isThisMonth(int year,int month) {
    final now = DateTime.now();
    return year == now.year && month == now.month;
  }

  //获得当前0点时间戳(毫秒)
  static int getToday0HourTime_ms(){
    String current=getStringTimeFormat();
    String today=current.substring(0,10);
    DateTime date = DateTime.parse(today);
    return date.millisecondsSinceEpoch;
  }

  //获得距离当前1个月前时间戳(毫秒)
  static int get1MonthAgoTime_ms(){
    return DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch;
  }

  //是否闰年
  static bool isRunNian(int year){
    if(year%4==0&&year%100!=0||year%400==0){
      return true;
    }
    return false;
  }

  //对应月份是否有
  static bool isMonth31Days(int month){
    if(month==1
        ||month==3
        ||month==5
        ||month==7
        ||month==8
        ||month==10
        ||month==12
    ){
      return true;
    }
    return false;
  }

  static int getDaysOfMonth(int year,int month){
    if(month==1
        ||month==3
        ||month==5
        ||month==7
        ||month==8
        ||month==10
        ||month==12
    ){
      return 31;
    }else if(month==2){
      if(isRunNian(year)){
        return 29;
      }
      return 28;
    }
    return 30;
  }




  //计算指定时间增加日时间后的时间,(Duration最大单位是日)
  static DateTime addDays(DateTime src, Duration time){
    // DateTime now = DateTime.now();
    // DateTime tomorrow = now.add(Duration(days: 1)); // 明天
    return src.add(time);
  }
  //计算指定时间减少日时间后的时间(Duration最大单位是日)
  static DateTime subDays(DateTime src, Duration time){
    // DateTime now = DateTime.now();
    // DateTime yesterday = now.subtract(Duration(days: 1)); // 昨天
    return src.subtract(time);
  }

  /*
  比较两个 DateTime 对象的大小
可以使用比较运算符 <、>、<=、>=、==、!= 来比较两个 DateTime 对象的大小：
DateTime now = DateTime.now();
DateTime otherTime = DateTime(2022, 8, 6);
bool isBefore = now.isBefore(otherTime); // true
bool isAfter = now.isAfter(otherTime); // false
end.compareTo(start)<0
   */
  static int compareTo(DateTime startDateTime,DateTime endDateTime){
    return endDateTime.compareTo(startDateTime);
  }

  //计算两个DateTime相差多少天
  static int getDifferenceDay(DateTime startDateTime,DateTime endDateTime){
    return endDateTime.difference(startDateTime).inDays;
  }

  static Duration getDifferenceDuration(DateTime startDateTime,DateTime endDateTime){
    return endDateTime.difference(startDateTime);
  }


  //是否本周
  static bool isThisWeek(int year,int week) {
    final now = DateTime.now();
    Map<String,dynamic> itemData=getYearWeekNumber(date:now);

    if(year == now.year && itemData['yearWeek']==week){
      return true;
    }
    return false;
  }


  //按年计算周数, 属于第几周
  static Map<String,dynamic> getYearWeekNumber({
    DateTime? date,
    int? year,
    int? month,
    int? day,
  }) {
    if(date==null){
      if(year!=null && month!=null && day!=null){
        date= DateTime(year,month,day);
      }else{
        date= DateTime.now();
      }
    }

    // 获取给定年份的第一天是星期几
    DateTime firstDayOfYear = DateTime(date.year, 1, 1);
    int firstDayOfWeek = firstDayOfYear.weekday;

    DateTime firstWeekStart;
    if(firstDayOfWeek==1){
      //1.1刚好星期一
      firstWeekStart=firstDayOfYear;
    }else{
      // 将第一天向后移动（7 - firstDayOfWeek + 1）天得到第一个完整周的开始
      firstWeekStart = firstDayOfYear.add(Duration(days: (7 - firstDayOfWeek + 1)));
    }

    //属于上一年的最后一周
    if(date.isBefore(firstWeekStart)){

      //计算前年有多少周
      int perWeeks=getWeeksOfYear(date.year-1);

      Map<String,DateTime> preRange= getYearWeekRanges(date.year-1,perWeeks);
      return {
        'year':date.year-1,
        'yearWeek':perWeeks,
        'start':preRange['start'],
        'end':preRange['end'],
      };
    }

    // 将第一个完整周的开始日期作为第一周的开始日期
    DateTime weekStart = firstWeekStart;
    DateTime weekEnd = weekStart.add(const Duration(days: 6));

    // 计算指定日期属于哪一周
    int weekNumber = 1;
    while (date.isAfter(weekEnd)) {
      weekStart = weekEnd.add(const Duration(days: 1));
      weekEnd = weekStart.add(const Duration(days: 6));
      weekNumber++;
    }

    return {
      'year':date.year,
      'yearWeek':weekNumber,
      'start':weekStart,
      'end':weekEnd,
    };
  }


//根据年周数算开始结束日期范围
  static Map<String,DateTime> getYearWeekRanges(int year,int week) {

    if(week<=0){
      week=1;
    }

    int weeks=getWeeksOfYear(year);

    if(week>weeks){
      week=weeks;
    }

    // 获取给定年份的第一天是星期几
    DateTime firstDayOfYear = DateTime(year, 1, 1);
    int firstDayOfWeek = firstDayOfYear.weekday;

    DateTime firstWeekStart;
    if(firstDayOfWeek==1){
      firstWeekStart=firstDayOfYear;
    }else{
      // 将第一天向后移动（7 - firstDayOfWeek + 1）天得到第一个完整周的开始
      firstWeekStart = firstDayOfYear.add(Duration(days: (7 - firstDayOfWeek + 1)));
    }


    // 将第一个完整周的开始日期作为第一周的开始日期
    DateTime weekStart = firstWeekStart;
    DateTime weekEnd = weekStart.add(const Duration(days: 6));
    //print('The date range of week 1 in $year is from $weekStart to $weekEnd.');

    if(week==1){
      return {
        'start':weekStart,
        'end':weekEnd
      };
    }

    // 计算其他每个周的开始和结束日期
    for (int weekNumber = 2; weekNumber <= weeks; weekNumber++) {
      weekStart = weekEnd.add(const Duration(days: 1));
      weekEnd = weekStart.add(const Duration(days: 6));
      if(week==weekNumber){
        break;
      }
    }

    return {
      'start':weekStart,
      'end':weekEnd
    };
  }

  static void printYearWeekRanges(int year) {
    // 获取给定年份的第一天是星期几
    DateTime firstDayOfYear = DateTime(year, 1, 1);
    int firstDayOfWeek = firstDayOfYear.weekday;//星期几:1~7

    DateTime firstWeekStart;
    if(firstDayOfWeek==1){
      //1.1刚好星期一
      firstWeekStart=firstDayOfYear;
    }else{
      // 将第一天向后移动（7 - firstDayOfWeek + 1）天得到第一个完整周的开始
      firstWeekStart = firstDayOfYear.add(Duration(days: (7 - firstDayOfWeek + 1)));
    }
    //计算当前年有多少周
    int weeks=getWeeksOfYear(year);

    // 将第一个完整周的开始日期作为第一周的开始日期
    DateTime weekStart = firstWeekStart;
    DateTime weekEnd = weekStart.add(const Duration(days: 6));
    XLogUtils.printLog('The date range of week 1 in $year is from $weekStart to $weekEnd.');

    // 计算其他每个周的开始和结束日期
    for (int weekNumber = 2; weekNumber <= weeks; weekNumber++) {
      weekStart = weekEnd.add(const Duration(days: 1));
      weekEnd = weekStart.add(const Duration(days: 6));

      XLogUtils.printLog('The date range of week $weekNumber in $year is from $weekStart to $weekEnd.');

      if (weekEnd.year != year) {
        break;
      }
    }
  }


  //计算当前年有多少周,52或53周 以1月第一个星期一作为开始
  static int getWeeksOfYear(int year){

    // 获取给定年份的第一天是星期几
    DateTime firstDayOfYear = DateTime(year, 1, 1);
    int firstDayOfWeek = firstDayOfYear.weekday;//星期几:1~7

    DateTime firstWeekStart;
    if(firstDayOfWeek==1){
      //1.1刚好星期一
      firstWeekStart=firstDayOfYear;
    }else{
      // 将第一天向后移动（7 - firstDayOfWeek + 1）天得到第一个完整周的开始
      firstWeekStart = firstDayOfYear.add(Duration(days: (7 - firstDayOfWeek + 1)));
    }
    //计算当前年有多少周
    int weeks=52;
    int days=isRunNian(year)?366:365;
    if(52*7+firstWeekStart.day-1<days){
      weeks=53;
    }

    return weeks;
  }


  //是否当季
  static bool isThisQuarter(int year,int quarter) {
    final now = DateTime.now();
    return year == now.year && quarter == getQuarterNumber(date: now);
  }

  /*
  获得对应所属的季度
   */
  static int getQuarterNumber({
    DateTime? date,
    int? year,
    int? month,
    int? day,
  }) {
    if(date==null){
      if(year!=null && month!=null && day!=null){
        date= DateTime(year,month,day);
      }else{
        date= DateTime.now();
      }
    }

    int monthR=date.month;

    if(monthR==1 || monthR==2||monthR==3){
      return 1;
    }else if(monthR==4 || monthR==5||monthR==6){
      return 2;
    }else if(monthR==7 || monthR==8||monthR==9){
      return 3;
    }else if(monthR==10 || monthR==11||monthR==12){
      return 4;
    }

    return 1;

  }
  /*
  获得对应所属的季度范围
   */
  static Map<String,DateTime> getQuarterRange(int year,int quarter) {

    if(quarter==2){
      return {
        'start':DateTime(year,4,1),
        'end': DateTime(year,6,30),
      };
    }else if(quarter==3){
      return {
        'start':DateTime(year,7,1),
        'end': DateTime(year,9,30),
      };
    }else if(quarter==4){
      return {
        'start':DateTime(year,10,1),
        'end': DateTime(year,12,31),
      };
    }{
      return {
        'start':DateTime(year,1,1),
        'end': DateTime(year,3,31),
      };
    }

  }


  //上个月
  static DateTime getPreMonthDateTime(DateTime dt){

    int year=dt.year;
    int month=dt.month;
    int day=dt.day;

    if(month==1){
      month=12;
      year=year-1;
    }else{
      month=month-1;
    }

    int preMonthMaxDays=getDaysOfMonth(year, month);
    if(day>preMonthMaxDays){
      day=preMonthMaxDays;
    }

    return DateTime(year,month,day,dt.hour,dt.minute,dt.second);

  }

}
